<?php
/**
 * XmuSlh, web platform of Student Association Federation of Xiamen University
 * 
 * Rewritting one or some pages of StatusNet. 
 * To get the original version, please visit <http://status.net/>.
 * 
 * StatusNet, the distributed open-source microblogging tool
 * 
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Base class for forms
 * 
 * We have a log of common forms, this superclass lets us abstract out the basic
 * features of the form.
 * 
 * Form可以抽象理解成HTML中的一个<form>标签, 他是一个页面中较为独立的一部分.
 * 
 * @author		ytukie <ytukie@gmail.com>
 * @version		0.21
 * 
 * 0.2)  Adds the 'args' to restore the fields (actually more than fields) value
 * 		 if is set.
 * 		 Adds 'getField' function to get the filled value of specific field.
 * 0.21) Adds the 'formToken' section.
 * 0.22) Adds the 'prepareData' section.
 * 0.3)  Removes the 'args', put it into Widget.
 */

// XmuSlh only.
if ( !defined('XMUSLH')) { exit(1); }

// Requirements.
require_once INSTALLDIR . '/lib/slh_util.php';
require_once INSTALLDIR . '/lib/slh_widget.php';


class Form extends Widget
{
	/**
	 * The attribute could set or return the MIME type of the encoded form content.
	 */
	var $enctype = null;
	
	function __construct($out, &$args = array())
	{
		parent::__construct($out, $args);
	}
	
	/**
	 * Show the form.
	 * 
	 * Uses a recipe to output the form.
	 */
	function show()
	{
		// Each attributes from the configured subclass.
		// id, class, method, action are all the HTML attributes.
		$attributes = array('id' 	 =>	$this->id(),
						    'class'	 => $this->formClass(),
						    'method' =>	$this->method(),
						    'action' =>	$this->action());
		
		// Check if has the enctype tag to uploading a file.
		if ( !empty($this->enctype)) {
			$attributes['enctype'] = $this->enctype;
		}
		
		// Output the content in a template pattern.
		$this->out->elementStart('form', $attributes);
		$this->prepareData();
		
		$this->out->elementStart('fieldset');
		
		$this->formLegend();
		$this->formToken();
		$this->sessionToken();
		$this->formData();
		$this->formActions();
		
		$this->out->elementEnd('fieldset');
		$this->out->elementEnd('form');		
	}
	
	/**
	 * Parepration for some datas.
	 */
	function prepareData()
	{
	}
	
	/**
	 * Name of the form
	 * 
	 * Sub-class should overload this with the name of their form.
	 */
	function formLegend()
	{
	}
	
	/**
	 * Token of the form.
	 * 
	 * To distinguish different form submitting in the same page.
	 * 
	 * TODO: Use name of the submit to instead?.
	 */
	function formToken()
	{
	}
	
	/**
	 * Include a session token for CSRF protection
	 */
	function sessionToken()
	{
		$this->out->hidden('token', slh_session_token());
	}

	/**
	 * Visible or invisible data elements.
	 * 
	 * Display the form fields that make up the data of the form.
	 * Sub-classes should overload this to show their data.
	 */
	function formData()
	{
	}
	
	/**
	 * HTTP method used to submit the form.
	 * 
	 * Defaults to post. Subclasses can override if they need to.
	 */
	function method()
	{
		return 'post';
	}
	
	/**
	 * Buttons for form actions.
	 * 
	 * Submit and cancel buttons (or whatever)
	 * Sub-clases should overload this to show their own buttons.
	 */
	function formActions()
	{
	}
	
	/**
	 * ID of the form.
	 * 
	 * Should be unique on the same page. Sub-classes should overload this
	 * to show their own IDs.
	 */
	function id()
	{
		return null;
	}
	
	/**
	 * Action of the form.
	 * 
	 * URL to post to. Should be overloaded by subclasses to give
	 * somewhere to post to.
	 */
	function action()
	{
	}
	
	/**
	 * Class of the form.
	 */
	function formClass()
	{
		return 'cls_form';
	}
	
	/**
	 * What? Start tag of the list. 
	 */
	function li()
	{
		$this->out->elementStart('li');
	}
	
	/**
	 * End tag of the list.
	 */
	function unli()
	{
		$this->out->elementEnd('li');
	}
}